package uk.co.agileworks.bidpirate.service;

import static uk.co.agileworks.bidpirate.service.EbayFacadeImpl.getCurrencyAndPrice;
import static uk.co.agileworks.bidpirate.service.EbayFacadeImpl.getCurrencyAndPriceSpan;

import javax.annotation.Resource;

import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;

import uk.co.agileworks.bidpirate.model.Bid;
import uk.co.agileworks.bidpirate.model.CurrencyAndPrice;
import uk.co.agileworks.bidpirate.model.User;

@Component
@Scope(value = "prototype", proxyMode = ScopedProxyMode.NO)
public final class EbaySessionImpl implements EbaySession {

	private static final Logger LOGGER = LoggerFactory.getLogger(EbaySessionImpl.class);

	private static final boolean ENABLE_JAVASCRIPT = false;

	private WebDriver driver;
	@Resource
	private String defaultUrl;
	@Resource
	private String placeBidUrl;
	@Resource
	private String signInUrl;

	public EbaySessionImpl() {
		driver = new HtmlUnitDriver(ENABLE_JAVASCRIPT);
	}

	@Override
	public String confirmBid() {
		assertState("BidReview");
		WebElement confirm = driver.findElement(By.xpath("//input[@name='btnSubmit']"));
		confirm.click();
		LOGGER.debug(driver.getCurrentUrl());
		LOGGER.trace(driver.getPageSource());
		return getBidStatus();
	}

	@Override
	public double getItemPrice() {
		assertState("ViewItem");
		String currencyAndPriceText = getCurrencyAndPriceSpan(driver).getText();
		CurrencyAndPrice currencyAndPrice = getCurrencyAndPrice(currencyAndPriceText);
		double itemPrice = currencyAndPrice.getPrice();
		LOGGER.debug("itemPrice=" + itemPrice);
		return itemPrice;
	}

	@Override
	public boolean isItemEnded(String itemUrl) {
		boolean itemEnded = true;
		driver.get(itemUrl);
		LOGGER.debug(driver.getCurrentUrl());
		LOGGER.trace(driver.getPageSource());
		try {
			driver.findElement(By.xpath("//span[text()='Ended:']"));
		} catch (NoSuchElementException e) {
			itemEnded = false;
		}
		LOGGER.debug("itemEnded=" + itemEnded);
		return itemEnded;
	}

	@Override
	public boolean isItemWon() {
		boolean itemWon = false;
		assertState("ViewItem");
		try {
			WebElement bidState = driver.findElement(By.xpath("//div[@id='BidStateTextControl']"));
			LOGGER.debug("bidState=[" + bidState.getText() + "]");
			itemWon = bidState.getText().startsWith("You won");
		} catch (NoSuchElementException e) {
			LOGGER.warn(e.toString());
		}
		LOGGER.debug("itemWon=" + itemWon);
		return itemWon;
	}

	@Override
	public boolean isSignedIn() {
		boolean signedIn = false;
		driver.get(defaultUrl);
		LOGGER.debug(driver.getCurrentUrl());
		LOGGER.trace(driver.getPageSource());
		WebElement loginStrong = driver.findElement(By.xpath("//td[@class='ttext']/strong"));
		LOGGER.debug("loginStrong=" + loginStrong.getText());
		signedIn = !loginStrong.getText().equals("Welcome!");
		LOGGER.debug("signedIn=" + signedIn);
		return signedIn;
	}

	@Override
	public void placeBid(Bid bid) {
		driver.get(placeBidUrl(bid.getItem().getItemNumber()));
		LOGGER.debug(driver.getCurrentUrl());
		LOGGER.trace(driver.getPageSource());
		WebElement yourBid = driver.findElement(By.xpath("//input[@name='bid']"));
		yourBid.clear();
		yourBid.sendKeys(String.valueOf(bid.getMaxBid()));
		LOGGER.debug("yourBid=" + yourBid);
		WebElement nextStep = driver.findElement(By.xpath("//input[@name='btnSubmit']"));
		nextStep.click();
		LOGGER.debug(driver.getCurrentUrl());
		LOGGER.trace(driver.getPageSource());
	}

	@Override
	public boolean signIn(User user) {
		driver.get(signInUrl);
		LOGGER.debug(driver.getCurrentUrl());
		LOGGER.trace(driver.getPageSource());
		LOGGER.debug("title=" + driver.getTitle());
		WebElement uid = driver.findElement(By.xpath("//input[@name='uid']"));
		WebElement upw = driver.findElement(By.xpath("//input[@name='upw']"));
		WebElement btnSubmit = driver.findElement(By.xpath("//input[@name='btnSubmit']"));
		uid.sendKeys(user.getUsername());
		upw.sendKeys(user.getPassword());
		btnSubmit.click();
		LOGGER.debug(driver.getCurrentUrl());
		LOGGER.trace(driver.getPageSource());
		LOGGER.debug("title=" + driver.getTitle());
		return !driver.getTitle().equals("eBay Mobile Sign in");
	}

	@Override
	public void signOut() {
		driver.get(signInUrl + "?so=Logout");
		LOGGER.debug(driver.getCurrentUrl());
		LOGGER.trace(driver.getPageSource());
	}

	String getBidStatus() {
		WebElement td = driver.findElement(By.xpath("//td[@class='ttext']"));
		String bidStatus = td.getText();
		LOGGER.debug("bidStatus=[" + bidStatus + "]");
		return bidStatus;
	}

	WebDriver getDriver() {
		return driver;
	}

	String placeBidUrl(long itemNumber) {
		return placeBidUrl.replace("%ITEM_NUMBER%", String.valueOf(itemNumber));
	}

	private void assertState(String pageName) {
		if (!driver.getCurrentUrl().contains(pageName)) {
			throw new IllegalStateException("Expected to be on the " + pageName
					+ " page, but was here [" + driver.getCurrentUrl() + "].");
		}
	}

}
